﻿using System;
using System.Collections.Generic;
#if NETFX_CORE
using Windows.UI.Xaml.Navigation;
#else
using System.Windows.Navigation;
#endif
using MugenMvvmToolkit.Interfaces;
using MugenMvvmToolkit.Interfaces.ViewModels;
using MugenMvvmToolkit.Interfaces.Views;

namespace MugenMvvmToolkit.Infrastructure
{
    /// <summary>
    ///     Represents the view model navigation cache policy, that clear the cache during back navigation.
    /// </summary>
    public class DefaultNavigationCachePolicy : INavigationCachePolicy
    {
        #region Fields

        private readonly Dictionary<Type, List<IViewModel>> _cachedViewModels;

        #endregion

        #region Constructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="DefaultNavigationCachePolicy" /> class.
        /// </summary>
        public DefaultNavigationCachePolicy()
        {
            _cachedViewModels = new Dictionary<Type, List<IViewModel>>();
        }

        #endregion

        #region Implementation of INavigationCachePolicy

        /// <summary>
        ///     Tries to save a view model in the cache.
        /// </summary>
        public virtual void TryCacheViewModel(INavigationContext context, IView view, IViewModel viewModel)
        {
            if (context.NavigationMode == NavigationMode.Back)
                return;
            Type type = view.GetType();
            List<IViewModel> list;
            if (!_cachedViewModels.TryGetValue(type, out list))
            {
                list = new List<IViewModel>();
                _cachedViewModels[type] = list;
            }
            list.Insert(0, viewModel);
        }

        /// <summary>
        ///     Tries to get view model from the cache, and delete it from the cache.
        /// </summary>
        public virtual IViewModel TryTakeViewModelFromCache(INavigationContext context, IView view)
        {
            List<IViewModel> list;
            if (!_cachedViewModels.TryGetValue(view.GetType(), out list) || list == null || list.Count == 0)
                return null;
            IViewModel vm = list[0];
            list.RemoveAt(0);
            return vm;
        }

        /// <summary>
        ///     Removes the view model from cache.
        /// </summary>
        public virtual bool Clear(IViewModel viewModel)
        {
            bool clear = false;
            foreach (var cachedViewModel in _cachedViewModels)
            {
                int indexOf = cachedViewModel.Value.IndexOf(viewModel);
                if (indexOf != -1)
                {
                    cachedViewModel.Value.RemoveAt(indexOf);
                    clear = true;
                }
            }
            return clear;
        }

        /// <summary>
        ///     Clears the cache.
        /// </summary>
        public virtual void Clear()
        {
            _cachedViewModels.Clear();
        }

        #endregion
    }
}